package controller;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;

import model.Model;
import model.entity.BasicEntity;
import model.handler.MovementHandler;
import model.interactionhandler.InteractionContainer;
import model.map.Direction;
import model.map.Location;
import model.map.World;
import model.skill.AngularProjectile;
import model.skill.LinearProjectile;
import model.skill.ProjectileInformation;
import model.skill.ProjectileLibrary;
import model.skill.RadialProjectile;
import model.skill.SelfProjectile;
import view.MapOverlay;
import view.View;

public class AvatarController extends Controller {

	BasicEntity avatar;
	JFrame gw;
	MovementHandler mh;
	MapOverlay mo;
	InteractionContainer ic;
	
	public AvatarController( final BasicEntity avatar, JFrame gameWindow, final MapOverlay mo, 
			InteractionContainer ic) {
		this.avatar = avatar;
		avatar.register( new View() {
			@Override
			public void update(Model m) {
					mo.setCenterLocation( avatar.getLocation() );
//					World.getInstance().getCurrentMap().updateFogOfWar();
			}
		});
		this.gw = gameWindow;
		mh = MovementHandler.getInstance();
		this.mo = mo;
		this.ic = ic;
		initiate();
	}
	
	@Override
	public void update(View v) {}

	private void moveNW() {
		if( !canMove() ) { return ; }
		mh.moveEntity( avatar, Direction.NW );
		mo.setCenterLocation( avatar.getLocation() );
	}
	
	private void moveN() {
		if( !canMove() ) { return ; }
		mh.moveEntity( avatar, Direction.N );
		mo.setCenterLocation( avatar.getLocation() );
	}
	
	private void moveNE() {
		if( !canMove() ) { return ; }
		mh.moveEntity( avatar, Direction.NE );
		mo.setCenterLocation( avatar.getLocation() );
	}
	
	private void moveSE() {
		if( !canMove() ) { return ; }
		mh.moveEntity( avatar, Direction.SE );
		mo.setCenterLocation( avatar.getLocation() );
	}
	
	private void moveS() {
		if( !canMove() ) { return ; }
		mh.moveEntity( avatar, Direction.S );
		mo.setCenterLocation( avatar.getLocation() );
	}
	
	private void moveSW() {
		if( !canMove() ) { return ; }
		mh.moveEntity( avatar, Direction.SW );
		mo.setCenterLocation( avatar.getLocation() );
	}

	private void attackRadial() { //TODO: REMOVE. USING FOR TESTING PURPOSES
		Location location = World.getInstance().getPlayer().getLocation();
		Direction avatarDirection = World.getInstance().getPlayer().getDirection();
		ProjectileInformation projectileInfo = new ProjectileInformation(location, avatarDirection);
		
		RadialProjectile radial = ProjectileLibrary.getInstance().getRadialProjectile("radialProjectileMediumSpeedAndHeavyDamageAndLongDistance");
		radial.propagate(projectileInfo);
	}
	
	private void attackAngular() { //TODO: REMOVE. USING FOR TESTING PURPOSES
		Location location = World.getInstance().getPlayer().getLocation();
		Direction avatarDirection = World.getInstance().getPlayer().getDirection();
		ProjectileInformation projectileInfo = new ProjectileInformation(location, avatarDirection);
		
		AngularProjectile angular = ProjectileLibrary.getInstance().getAngularProjectile("angularProjectileMediumSpeedAndHeavyDamageAndLongDistance");
		angular.propagate(projectileInfo);
	}
	
	private void attackLinear() { //TODO: REMOVE. USING FOR TESTING PURPOSES
		Location location = World.getInstance().getPlayer().getLocation();
		Direction avatarDirection = World.getInstance().getPlayer().getDirection();
		ProjectileInformation projectileInfo = new ProjectileInformation(location, avatarDirection);
		
		LinearProjectile linear = ProjectileLibrary.getInstance().getLinearProjectile("linearProjectileMediumSpeedAndHeavyDamageAndLongDistance");
		linear.propagate(projectileInfo);
	}
	
	private void healDamage() { //TODO: REMOVE. USING FOR TESTING PURPOSES
		Location location = World.getInstance().getPlayer().getLocation();
		Direction avatarDirection = World.getInstance().getPlayer().getDirection();
		ProjectileInformation projectileInfo = new ProjectileInformation(location, avatarDirection);
		
		SelfProjectile self = ProjectileLibrary.getInstance().getSelfProjectile("selfProjectileHealDamage");
		self.propagate(projectileInfo);
	}
	
	private boolean canMove() {
		return ! this.ic.isInteracting();
	}
	
	private void initiate() {
		gw.addKeyListener( new KeyListener() {
			@Override
			public void keyPressed(KeyEvent arg0) {
				if( arg0.getKeyCode() == GameConfig.MOVE_NW ) {
					moveNW();
				}
			}
			@Override
			public void keyReleased(KeyEvent arg0) {}
			@Override
			public void keyTyped(KeyEvent arg0) {}
		});
		gw.addKeyListener( new KeyListener() {
			@Override
			public void keyPressed(KeyEvent arg0) {
				if( arg0.getKeyCode() == GameConfig.MOVE_N ) {
					moveN();
				}
			}
			@Override
			public void keyReleased(KeyEvent arg0) {}
			@Override
			public void keyTyped(KeyEvent arg0) {}
		});
		gw.addKeyListener( new KeyListener() {
			@Override
			public void keyPressed(KeyEvent arg0) {
				if( arg0.getKeyCode() == GameConfig.MOVE_NE ) {
					moveNE();
				}
			}
			@Override
			public void keyReleased(KeyEvent arg0) {}
			@Override
			public void keyTyped(KeyEvent arg0) {}
		});
		gw.addKeyListener( new KeyListener() {
			@Override
			public void keyPressed(KeyEvent arg0) {
				if( arg0.getKeyCode() == GameConfig.MOVE_SE ) {
					moveSE();
				}
			}
			@Override
			public void keyReleased(KeyEvent arg0) {}
			@Override
			public void keyTyped(KeyEvent arg0) {}
		});
		gw.addKeyListener( new KeyListener() {
			@Override
			public void keyPressed(KeyEvent arg0) {
				if( arg0.getKeyCode() == GameConfig.MOVE_S ) {
					moveS();
				}
			}
			@Override
			public void keyReleased(KeyEvent arg0) {}
			@Override
			public void keyTyped(KeyEvent arg0) {}
		});
		gw.addKeyListener( new KeyListener() {
			@Override
			public void keyPressed(KeyEvent arg0) {
				if( arg0.getKeyCode() == GameConfig.MOVE_SW ) {
					moveSW();
				}
			}
			@Override
			public void keyReleased(KeyEvent arg0) {}
			@Override
			public void keyTyped(KeyEvent arg0) {}
		});
		
		gw.addKeyListener( new KeyListener() {//TODO: REMOVE. USING FOR TESTING PURPOSES
			@Override
			public void keyPressed(KeyEvent arg0) {
				if( arg0.getKeyCode() == GameConfig.ATTACK_RADIAL ) {
					attackRadial();
				}
			}
			@Override
			public void keyReleased(KeyEvent arg0) {}
			@Override
			public void keyTyped(KeyEvent arg0) {}
		});
		
		gw.addKeyListener( new KeyListener() {//TODO: REMOVE. USING FOR TESTING PURPOSES
			@Override
			public void keyPressed(KeyEvent arg0) {
				if( arg0.getKeyCode() == GameConfig.ATTACK_ANGULAR ) {
					attackAngular();
				}
			}
			@Override
			public void keyReleased(KeyEvent arg0) {}
			@Override
			public void keyTyped(KeyEvent arg0) {}
		});
		
		gw.addKeyListener( new KeyListener() {//TODO: REMOVE. USING FOR TESTING PURPOSES
			@Override
			public void keyPressed(KeyEvent arg0) {
				if( arg0.getKeyCode() == GameConfig.ATTACK_LINEAR ) {
					attackLinear();
				}
			}
			@Override
			public void keyReleased(KeyEvent arg0) {}
			@Override
			public void keyTyped(KeyEvent arg0) {}
		});
		
		gw.addKeyListener( new KeyListener() {//TODO: REMOVE. USING FOR TESTING PURPOSES
			@Override
			public void keyPressed(KeyEvent arg0) {
				if( arg0.getKeyCode() == GameConfig.HEAL_DAMAGE ) {
					healDamage();
				}
			}
			@Override
			public void keyReleased(KeyEvent arg0) {}
			@Override
			public void keyTyped(KeyEvent arg0) {}
		});
	}
	
}
